kafka ISR设计及水印与leader epoch副本同步机制深入剖析
帽子理论(Gilbert 和 Lynch )
一致性
1
2
3
4
5
6
7
8
9
10
11
12
13any read operation that begins after a write operation completes must
return that value, or the result of a later write operation
通过某个节点的写操作结果对后面通过其它节点的读操作可见
强一致性:
如果更新数据后,并发访问情况下后续读操作可立即感知该更新,称为强一致性。
弱一致性:
如果允许之后部分或者全部感知不到该更新,称为弱一致性。
最终一致性:
若在之后的一段时间(通常该时间不固定)后,一定可以感知到该更新,称为最终一致性。可用性(Availability)
1
2
3every request received by a non-failing node in the system must result in a response
任何一个没有发生故障的节点必须在有限的时间内返回合理的结果。分区容忍性(Partition Tolerance)
1
2
3the network will be allowed to lose arbitrarily many messages sent from one node to another
部分节点宕机或者无法与其它节点通信时,各分区间还可保持分布式系统的功能。悖论总结:
可用性限定在无论是否集群节点宕机,只要有活着的节点,就会立即返回请求结果。若要限制返回结果必须是最近一次写的结果,就比较悲剧,若允许分区容忍性 => 分布式系统分区之间就存在数据同步机制,那么就有可能因为分区心跳切断,导致数据不一致。
partition本质就是为了日志备份(对外最小的存储单元)
Kafka中topic的每个partition有一个预写式的日志文件,虽然partition可以继续细分为若干个segment文件,但是对于上层应用来说可以将partition看成最小的存储单元(一个有多个segment文件拼接的“巨型”文件),每个partition都由一些列有序的、不可变的消息组成,这些消息被连续的追加到partition中。
- partition本质就是为了日志备份,利用多份日志文件的副本(replica)备份来共同提供冗余机制来保持系统的高可用性。
- kafka会把副本均匀的分配到所有的Broker上。在其中所有的副本中,会挑选一个Leader副本来对外提供服务,其他的副本统称为follower副本,只能被动的向leader副本请求数据。
Partitioner 三分天下
下图展示了3个Partition把一个Topic主题数据流分成三份,通过Partioner路由依次追加到分区的末尾中。如果partition规则设置的合理,所有消息可以均匀分布到不同的partition里,这样就实现了水平扩展。
config/server.properties可以设置num.partitions参数,实现主题数据分流。
Leader副本竞选上岗(in-sync replicas)
- 每一个分区都存在一个in-sync replicas。
- in-sync replicas集合中的每一个副本都与leader保持同步状态,不在里面的保持不了同步状态。
- 只有ISR中的副本才有资格被选为leader。
- Producer写入的消息只有被ISR中的副本都接收到,才被视为”已提交”。
水印HW与末端位移LEO => Leader副本
- 这里着重强调一下,Leader副本水印HW才真正决定了对外可看到的消息数量。
- 所有的副本都有LEO和HW。
- Leader副本水印HW的更新发生在所有的副本都更新了最新的LEO后,Leader副本最终才认为可以更新Leader副本水印。
ISR设计优化(replica.lag.max.messages废弃)
- 解决了producer突然发起一大波消息,从而产生瞬时高峰流量。若设置replica.lag.max.messages=4,则follower副本会被瞬时的拉开距离,从而导致follower副本瞬间被踢出ISR。不过一段时间follower副本同步后,会再次进入ISR。
- 同步不同步,同步不同步反复出现,是多大的性能浪费。
- 0.9.0.0开始采用 replica. lag. time. max. ms,默认是10s,可谓是明智之举。
HW同步机制
HW指向哪里?
- 这里重点强调,都是无论HW还是LEO都是指向下一条消息
- 举例如下:如果一个普通topic的某个分区副本的LEO是10,那么该副本当前保存了10条消息,位移值范围是[0, 9]。此时若有一个producer向该副本插入一条消息,则该条消息的位移值是10,而副本LEO值则更新成11。
Leader与follower的HW(两阶段请求定终身)
- follower 副本会不断地向leader副本发送Fetch请求
(1)follower 副本对象何时更新LEO?
1 | follower 副本专属线程不断地向leader副本所在broker发送FETCH请求。 |
(2)leader 端非自己副本对象何时更新LEO?
1 | leader 端非自己副本对象 LEO值是在leader端broker处理FETCH请求过程中被更新的。 |
(3) follower 副本对象何时更新HW?
1 | Follower 副本对象更新HW是在其更新本地LEO之后。 |
(4)leader 副本对象何时更新HW?
1 | Leader 副本对象处理 Follower FETCH请求时在更新完leader 端非自己副本对象的LEO后将尝试更新其自己HW值 |
(5)两阶段请求定终身:
第一次fetch请求仅获得了当前的数据,fetchOffset < Leader LEO, 因为leader 端的非自己的副本leo 是根据fetch请求确定的,因此,只有第二次请求时,fetchOffset才会和Leader LEO相等,进而更新 leader HW ,进而响应为 leader HW,进而更新 Folloer HW。
HW更新延迟带来的刀山火海
- 因为 fetchOffset是实实在在的需要位移。所以只有第二轮请求时,Follower才会在其现有位移的基础上,加1进行请求,从而连锁更新 会更新Leader非自己remoteLEO 和 Leader HW 和 Follower HW。
- 刀山火海就在一轮请求和第二轮请求之间发生了。
- 本文链接:https://gjtmaster.github.io/2018/09/23/kafka ISR设计及水印与leader epoch副本同步机制深入剖析/
- 版权声明:The author owns the copyright, please indicate the source reproduced.